
#import <QuartzCore/QuartzCore.h>

#import "ZCSlotMachine.h"



#define MCSingleUnitDuration 0.14f

static BOOL _isRotating = NO;
static const NSUInteger kMinTurn = 3;

/********************************************************************************************/

@implementation ZCSlotMachine {
@private
    // UI
    UIView *_view_back;
    UIEdgeInsets _contentInset;
    NSMutableArray *_slotScrollLayerArray;
    
    // Data
    NSArray *_slotResults;
    NSArray *_currentSlotResults;
    
    __weak id<ZCSlotMachineDataSource> _dataSource;
}

#pragma mark - View LifeCycle

- (id)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    if (self) {
        self.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
        _view_back = [[UIView alloc] initWithFrame:self.bounds];
        [self addSubview:_view_back];
        
        _slotScrollLayerArray = [NSMutableArray array];
        
        self.singleUnitDuration = MCSingleUnitDuration;
        
        _contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
    }
    return self;
}

#pragma mark - Properties Methods



- (UIEdgeInsets)contentInset {
    return _contentInset;
}

- (void)setContentInset:(UIEdgeInsets)contentInset {
    _contentInset = contentInset;
    
//    CGRect viewFrame = self.frame;
    
    //    _contentView.frame = CGRectMake(_contentInset.left, _contentInset.top, viewFrame.size.width - _contentInset.left - _contentInset.right, viewFrame.size.height - _contentInset.top - _contentInset.bottom);
}

- (NSArray *)slotResults {
    return _slotResults;
}

- (void)setSlotResults:(NSArray *)slotResults {
    if (!_isRotating) {
        _slotResults = slotResults;
        
        if (!_currentSlotResults) {
            NSMutableArray *currentSlotResults = [NSMutableArray array];
            for (int i = 0; i < [slotResults count]; i++) {
                [currentSlotResults addObject:[NSNumber numberWithUnsignedInteger:0]];
            }
            _currentSlotResults = [NSArray arrayWithArray:currentSlotResults];
        }
    }
}

- (id<ZCSlotMachineDataSource>)dataSource {
    return _dataSource;
}

- (void)setDataSource:(id<ZCSlotMachineDataSource>)dataSource {
    _dataSource = dataSource;
    
    [self reloadData];
}

- (void)reloadData {
    if (self.dataSource) {
        
        for (CALayer *containerLayer in _view_back.layer.sublayers) {
            [containerLayer removeFromSuperlayer];
        }
        _slotScrollLayerArray = [NSMutableArray array];
        
        /*
         * 显示小球的个数
         */
        NSUInteger num_ShowBall = [self.dataSource numberOfSlotsInSlotMachine:self];
        
        CGFloat slotSpacing = 0;
        if ([self.dataSource respondsToSelector:@selector(slotSpacingInSlotMachine:)]) {
            slotSpacing = [self.dataSource slotSpacingInSlotMachine:self];
        }
        
        /*
         * 小球容器宽度设置
         */
        CGFloat W_square = _view_back.frame.size.width / num_ShowBall;
        
        if ([self.dataSource respondsToSelector:@selector(slotWidthInSlotMachine:)]) {
            //60
            W_square = [self.dataSource slotWidthInSlotMachine:self];
            
        }
        
        for (int i = 0; i < num_ShowBall; i++) {
            
            CALayer *layer_BallBack = [[CALayer alloc] init];
            CGFloat L = i * W_square;
            CGFloat H = _view_back.frame.size.height/3;
            //            CGFloat H = W_square;
            CGFloat W = W_square;
            layer_BallBack.frame = CGRectMake(L, 0,W ,H );
            layer_BallBack.masksToBounds = YES;
            layer_BallBack.borderColor = [UIColor yellowColor].CGColor;
            layer_BallBack.borderWidth = 10;
            CALayer *layer_ball = [[CALayer alloc] init];
            
            
            layer_ball.frame = CGRectMake(
                                          0,
                                          -H,
                                          W_square,
                                          H
                                          );
            
            layer_ball.borderColor = [UIColor greenColor].CGColor;
            layer_ball.borderWidth = 10;
            
            [layer_BallBack addSublayer:layer_ball];
            
            [_view_back.layer addSublayer:layer_BallBack];
            
            [_slotScrollLayerArray addObject:layer_ball];
        }

        CGFloat H_square = _view_back.frame.size.height / 3;
        //        CGFloat H_square = W_square;
        
        /*
         * 数据源
         */
        //0-9
        NSArray *arr_Icons = [self.dataSource imgIcons_ForSlotsInSlotMachine:self];
        
        //10
        NSUInteger num_AllIcons = [arr_Icons count];
        
        //5
        for (int i = 0; i < num_ShowBall; i++) {
            
            CALayer *layer_ball = [_slotScrollLayerArray objectAtIndex:i];
            
            //            6*11——11*11
            NSInteger scrollLayerTopIndex = - (i + kMinTurn + 3) * num_AllIcons;
            
            for (int j = 0; j > scrollLayerTopIndex; j--) {
                
                UIImage *img_icon = [arr_Icons objectAtIndex:abs(j) % num_AllIcons];
                
                CALayer *layer_iconImage = [[CALayer alloc] init];
                
                // adjust the beginning offset of the first unit
                
                NSInteger offsetYUnit = j + 1 + num_AllIcons;
                
                layer_iconImage.frame = CGRectMake(
                                                   0,
                                                   offsetYUnit * H_square,
                                                   layer_ball.frame.size.width,
                                                   H_square);
                
                layer_iconImage.contents = (id)img_icon.CGImage;
                layer_iconImage.contentsScale = img_icon.scale;
                layer_iconImage.contentsGravity = kCAGravityCenter;
                
                layer_iconImage.borderColor = [UIColor redColor].CGColor;
                layer_iconImage.borderWidth = 1;
                
                [layer_ball addSublayer:layer_iconImage];
            }
        }
    }
}

#pragma mark - Public Methods

- (void)startSliding {
    
    if (_isRotating) {
        return;
    }
    else {
        
        
        _isRotating = YES;
        
        /*
         * 摇奖将要开始
         */
        if ([self.delegate respondsToSelector:@selector(slotMachineWillStartSliding:)]) {
            [self.delegate slotMachineWillStartSliding:self];
        }
        
        //0-9
        
        NSArray *arr_Icons = [self.dataSource imgIcons_ForSlotsInSlotMachine:self];
        
        //10
        NSUInteger num_AllIcons = [arr_Icons count];
        
        __block NSMutableArray *completePositionArray = [NSMutableArray array];
        
        [CATransaction begin];
        
        [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
        
        [CATransaction setDisableActions:YES];
        
        
        /*
         * 动画结束调用
         */
        [CATransaction setCompletionBlock:^{
            
            
            _isRotating = NO;
            
            if ([self.delegate respondsToSelector:@selector(slotMachineDidEndSliding:)]) {
                [self.delegate slotMachineDidEndSliding:self];
            }
            
            for (int i = 0; i < [_slotScrollLayerArray count]; i++) {
                CALayer *slotScrollLayer = [_slotScrollLayerArray objectAtIndex:i];
                
                slotScrollLayer.position = CGPointMake(slotScrollLayer.position.x, ((NSNumber *)[completePositionArray objectAtIndex:i]).floatValue);
                
                NSMutableArray *toBeDeletedLayerArray = [NSMutableArray array];
                
                NSUInteger resultIndex = [[self.slotResults objectAtIndex:i] unsignedIntegerValue];
                NSUInteger currentIndex = [[_currentSlotResults objectAtIndex:i] unsignedIntegerValue];
                
                for (int j = 0; j < num_AllIcons * (kMinTurn + i) + resultIndex - currentIndex; j++) {
                    CALayer *iconLayer = [slotScrollLayer.sublayers objectAtIndex:j];
                    [toBeDeletedLayerArray addObject:iconLayer];
                }
                
                for (CALayer *toBeDeletedLayer in toBeDeletedLayerArray) {
                    // use initWithLayer does not work
                    CALayer *toBeAddedLayer = [CALayer layer];
                    toBeAddedLayer.frame = toBeDeletedLayer.frame;
                    toBeAddedLayer.contents = toBeDeletedLayer.contents;
                    toBeAddedLayer.contentsScale = toBeDeletedLayer.contentsScale;
                    toBeAddedLayer.contentsGravity = toBeDeletedLayer.contentsGravity;
                    
                    CGFloat shiftY = num_AllIcons * toBeAddedLayer.frame.size.height * (kMinTurn + i + 3);
                    toBeAddedLayer.position = CGPointMake(toBeAddedLayer.position.x, toBeAddedLayer.position.y - shiftY);
                    
                    [toBeDeletedLayer removeFromSuperlayer];
                    [slotScrollLayer addSublayer:toBeAddedLayer];
                }
                toBeDeletedLayerArray = [NSMutableArray array];
            }
            
            _currentSlotResults = self.slotResults;
            completePositionArray = [NSMutableArray array];
            
            
        }];
        
        static NSString * const keyPath = @"position.y";
        
        for (int i = 0; i < [_slotScrollLayerArray count]; i++) {
            CALayer *slotScrollLayer = [_slotScrollLayerArray objectAtIndex:i];
            
            NSUInteger resultIndex = [[self.slotResults objectAtIndex:i] unsignedIntegerValue];
            NSUInteger currentIndex = [[_currentSlotResults objectAtIndex:i] unsignedIntegerValue];
            
            NSUInteger howManyUnit = (i + kMinTurn) * num_AllIcons + resultIndex - currentIndex;
            CGFloat slideY = howManyUnit * (_view_back.frame.size.height / 3);
            
            CABasicAnimation *slideAnimation = [CABasicAnimation animationWithKeyPath:keyPath];
            slideAnimation.fillMode = kCAFillModeForwards;
            slideAnimation.duration = howManyUnit * self.singleUnitDuration;
            slideAnimation.toValue = [NSNumber numberWithFloat:slotScrollLayer.position.y + slideY];
            slideAnimation.removedOnCompletion = NO;
            
            [slotScrollLayer addAnimation:slideAnimation forKey:@"slideAnimation"];
            
            [completePositionArray addObject:slideAnimation.toValue];
        }
        
        [CATransaction commit];
    }
}

@end
